<?php

namespace Xin\ThinkPHP\Model;

use think\db\Query;
use Xin\Support\SQL;
use Xin\Support\Time;

/**
 * @method self search(array $data, array $withoutFields = [])
 */
trait HasSearch
{
    /**
     * @var array
     */
    protected $searchMatchLikeFields = [];

    /**
     * 搜索数据作用域
     * @param Query $query
     * @param array $data
     * @param array $withoutFields
     * @return void
     * @throws \ReflectionException
     */
    public function scopeSearch(Query $query, array $data, array $withoutFields = [])
    {
        $data = array_filter($data, 'filled');

        $fields = array_diff(static::getSearchFields(), $withoutFields);
        $fields = array_intersect($fields, array_keys($data));

        // 获取要匹配Like的字段
        $matchLikeFields = $this->getSearchMatchLikeFields();
        if (!empty($matchLikeFields)) {
            $configProperty = new \ReflectionProperty($query->getConnection(), 'config');
            $configProperty->setAccessible(true);
            $connectionConfig = $configProperty->getValue($query->getConnection());
            $connectionConfig['match_like_fields'] = $matchLikeFields;
            $configProperty->setValue($query->getConnection(), $connectionConfig);
        }

        $query->withSearch($fields, $data);
    }

    /**
     * 获取搜索器要匹配Like的字段
     * @return array
     */
    protected function getSearchMatchLikeFields()
    {
        return $this->searchMatchLikeFields;
    }

    /**
     * 设置搜索器要匹配Like的字段
     * @return array
     */
    public function setSearchMatchLikeFields($matchLikeFields)
    {
        return $this->searchMatchLikeFields = $matchLikeFields;
    }

    /**
     * 标题搜索器
     * @param Query $query
     * @param string $value
     * @return void
     */
    public function searchKeywordsAttr(Query $query, $value)
    {
        $values = SQL::keywords($value);
        if (empty($values)) {
            return;
        }

        $query->where(implode('|', static::getSearchKeywordFields()), 'like', $values);
    }

    /**
     * 注册时间搜索器
     * @param Query $query
     * @param string $value
     * @return void
     */
    public function searchCreateTimeAttr(Query $query, $value)
    {
        $value = Time::parseRange($value);
        $query->whereBetweenTime('create_time', $value[0], $value[1]);
    }

    /**
     * 获取要搜索的字段列表
     * @return array
     */
    public static function getSearchFields()
    {
        $allowSearchFields = method_exists(static::class, 'getSimpleFields') ? static::getSimpleFields() : [];

        $keywordParameter = static::getSearchKeywordParameter();
        if ($keywordParameter) {
            return array_merge($allowSearchFields, is_array($keywordParameter) ? [
                $keywordParameter[0] => $keywordParameter[1],
            ] : [$keywordParameter]);
        }

        return $allowSearchFields;
    }

    /**
     * 获取关键字搜索字段
     * @return string[]
     */
    public static function getSearchKeywordFields()
    {
        return ["title"];
    }

    /**
     * 获取关键字搜索参数
     * @return string
     */
    public static function getSearchKeywordParameter()
    {
        return "keywords";
    }
}